#include <iostream>
#include "HTTPRequest.h"

HTTPRequest::HTTPRequest() : http_code(OK), REQUEST_STATE(PARSE_STATE::REQUEST_LINE),
                             method(), url(), version(), body(),
                             request_header(), request_body() {
    request_header.clear();
    request_body.clear();
}

HTTPRequest::~HTTPRequest() = default;

void HTTPRequest::pares_request(const Buffer &request) {
    const std::string &_request = request.get();
    const std::string CRLF = "\r\n";
    std::string::size_type start = 0;
    std::string::size_type end = _request.find(CRLF);
    std::string line_of_request;

    if (_request.empty()) {
        this->http_code = BAD_REQUEST;
        return;
    }
    // 状态机解析HTTP请求
    while (REQUEST_STATE != PARSE_STATE::REQUEST_DONE) {
        switch (REQUEST_STATE) {
            case PARSE_STATE::REQUEST_LINE:  // 处理请求行
                if (end == std::string::npos) {
                    std::cerr << "Error parsing request line.\n";
                    this->http_code = BAD_REQUEST;
                    return;
                }
                line_of_request = _request.substr(start, end - start);
                if (!this->pares_request_line(line_of_request)) {
                    std::cerr << "Error parsing request line.\n";
                    this->http_code = BAD_REQUEST;
                    return;
                }
                start = end + 2;
                end = _request.find(CRLF + CRLF, start);
                REQUEST_STATE = PARSE_STATE::REQUEST_HEAD;
                break;
            case PARSE_STATE::REQUEST_HEAD:  // 处理请求头
                if (end == std::string::npos) {
                    std::cerr << "Error parsing request head.\n";
                    this->http_code = BAD_REQUEST;
                    return;
                }
                line_of_request = _request.substr(start, end - start);
                this->pares_request_head(line_of_request);

                if (this->request_header.count("Content-Length") > 0) {
                    // 存在请求体数据
                    end += 4;
                    line_of_request = _request.substr(end);
                    REQUEST_STATE = PARSE_STATE::REQUEST_BODY;
                } else {
                    REQUEST_STATE = PARSE_STATE::REQUEST_DONE;
                }
                break;
            case PARSE_STATE::REQUEST_BODY:  // 处理请求体
                // 请求体数据错误判断应该不影响请求
                if (line_of_request.empty()) {
                    std::cerr << "Error parsing request body.\n";
                    REQUEST_STATE = PARSE_STATE::REQUEST_DONE;
                }
                if (this->pares_request_body(line_of_request)) {
                    REQUEST_STATE = PARSE_STATE::REQUEST_DONE;
                }
                break;
            default:
                std::cerr << "Error parsing request.\n";
                REQUEST_STATE = PARSE_STATE::REQUEST_DONE;
                this->http_code = BAD_REQUEST;
                return;
        }
    }
    this->http_code = OK;
}


bool HTTPRequest::pares_request_line(const std::string &line) {
    std::regex pattern("^([^ ]*) ([^ ]*) HTTP/([^ ]*)$");
    std::smatch string_match;
    if (regex_match(line, string_match, pattern)) {
        this->method = string_match[1];
        this->url = string_match[2];
        this->version = string_match[3];
        return true;
    }
    return false;

}

void HTTPRequest::pares_request_head(const std::string &line) {
    std::regex pattern(R"(([\w-]+):\s*(.*))");

    std::sregex_iterator it(line.begin(), line.end(), pattern);
    std::sregex_iterator end;
    while (it != end) {
        std::smatch match = *it;
        this->request_header[match[1].str()] = match[2].str();
        ++it;
    }
}

// 这里以仅解析POST请求和数据格式“application/x-www-form-urlencoded”数据为例，解析其他格式的请求体数据最好使用框架或第三方库
// 如果请求报文中存在查询字符串应该也要放在请求体里去解析处理
bool HTTPRequest::pares_request_body(const std::string &line) {
    if (this->method != "POST" && this->request_header["Content-Type"] != "application/x-www-form-urlencoded") {
        return false;
    }
    // 示例数据：name=John&age=30&address=123%20Main%20St.
    std::string::size_type start_pos = 0;
    while (start_pos < line.size()) {
        // Find the next key-value pair
        std::string::size_type end_pos = line.find_first_of('&', start_pos);
        if (end_pos == std::string::npos) {
            end_pos = line.size();
        }
        std::string::size_type separator_pos = line.find_first_of('=', start_pos);
        if (separator_pos == std::string::npos || separator_pos >= end_pos) {
            return false;
        }
        std::string key = line.substr(start_pos, separator_pos - start_pos);
        std::string value = line.substr(separator_pos + 1, end_pos - separator_pos - 1);
        // URL-decode the key-value pair
        for (char &i: key) {
            if (i == '+') {
                i = ' ';
            }
        }
        for (char &i: value) {
            if (i == '+') {
                i = ' ';
            }
        }
        for (size_t i = 0; i < key.size(); ++i) {
            if (key[i] == '%' && i + 2 < key.size()) {
                char ch = static_cast<char>(std::stoi(key.substr(i + 1, 2), nullptr, 16));
                key.replace(i, 3, 1, ch);
            }
        }
        for (size_t i = 0; i < value.size(); ++i) {
            if (value[i] == '%' && i + 2 < value.size()) {
                char ch = static_cast<char>(std::stoi(value.substr(i + 1, 2), nullptr, 16));
                value.replace(i, 3, 1, ch);
            }
        }
        // Store the key-value pair in the result map
        request_body[key] = value;
        start_pos = end_pos + 1;
    }

    return true;
}

bool HTTPRequest::is_keep_alive() const {
    if (request_header.count("Connection") > 0) {
        std::string keep_alive(request_header.at("Connection"));
        std::string_view keep_alive2("keep-alive");

        return std::equal(keep_alive.begin(), keep_alive.end(), keep_alive2.begin(), [](char a, char b) {
            return std::tolower(a) == std::tolower(b);
        });
//        return  ==  || request_header.at("Connection") == "Keep-Alive";
    }
    return false;
}

HTTP_CODE HTTPRequest::get_http_code() const {
    return this->http_code;
}

const std::string &HTTPRequest::get_method() const {
    return this->method;
}

const std::string &HTTPRequest::get_url() const {
    return this->url;
}

const std::string &HTTPRequest::get_version() const {
    return this->version;
}

const std::string &HTTPRequest::get_body() const {
    return this->body;
}

const std::unordered_map<std::string, std::string> &HTTPRequest::get_request_header() const {
    return this->request_header;
}

const std::unordered_map<std::string, std::string> &HTTPRequest::get_request_body() const {
    return this->request_body;
}

